#include <iostream>
#include <string>
#include <muduo/net/TcpClient.h>
#include <muduo/net/TcpConnection.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/Buffer.h>
#include <muduo/base/CountDownLatch.h>
#include <muduo/net/EventLoopThread.h>

class DictClient
{
public:
    DictClient(const std::string &serverIP, const uint16_t serverPort)
        : _eventLoop(_threadLoop.startLoop()),
          _dictClient(_eventLoop, muduo::net::InetAddress(serverIP, serverPort), "DictClient"),
          _downLatch(1) // 初始化计数器为1，当成功建立连接，计数器减为0，此时可以发送数据
    {
        _dictClient.setConnectionCallback(std::bind(&DictClient::onConnection, this, std::placeholders::_1));
        _dictClient.setMessageCallback(std::bind(&DictClient::onMessage,
                                                 this,
                                                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

        _dictClient.connect();
        _downLatch.wait(); // 等待计数器减为0
    }

    bool send(const std::string &message)
    {
        if (_con->connected() == false)
        {
            std::cout << "连接断开，发送失败！！" << std::endl;
            return false;
        }
        _con->send(message);
        return true;
    }

private:
    void onConnection(const muduo::net::TcpConnectionPtr &con)
    {
        if (con->connected())
        {
            std::cout << "连接建立" << std::endl;
            _con = con;
            _downLatch.countDown(); // 计数器--
        }
        else
            std::cout << "连接断开" << std::endl;
    }
    void onMessage(const muduo::net::TcpConnectionPtr &con, muduo::net::Buffer *buffer, muduo::Timestamp)
    {
        std::string recv_string = buffer->retrieveAllAsString();
        std::cout << recv_string << std::endl;
    }

private:
    // 需要启动loop()循环开始事件监控，但是这是一个死循环，如果直接放到成员函数中，就会导致程序无法继续运行
    // 可以利用一个线程来loop
    muduo::net::EventLoopThread _threadLoop;
    muduo::net::EventLoop *_eventLoop;

    muduo::net::TcpClient _dictClient;
    muduo::net::TcpConnectionPtr _con;
    muduo::CountDownLatch _downLatch;
};

int main()
{
    DictClient client("127.0.0.1", 8080);
    while (1)
    {
        std::string massage;
        std::cin >> massage;
        client.send(massage);
    }
    return 0;
}